﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Text.RegularExpressions;
using System.Threading;


namespace Kaixin.House.Garden
{
    using Kaixin.Tools;

    public class Garden
    {
        public enum ActionType
        {
            Harvest = 0,
            AntiGrass,
            Water,
            AntiVermin,
            Plough,
            FarmSeedRandom,
            FarmSeed,
        }

        private Network _network;

        private string _uid;     // your uid of this garden
        private string _fuid;    // friend uid (owner) of this garden, for harvest
        private string _verify;  // verify code for harvest
        private bool _FlowerWomen;
        private bool _CaiLaoBo;
        //private bool _Locked;    //true if all the farm in the garden locked, other wise, false;

        private Friend _friend = null;

        private AntiTheive _Anti = null;
        private MySeedList _MySeeds = null; // myself
        
        private List<Farm> _FarmList = new List<Farm>();

       

        public List<Farm> FarmList
        {
            get
            {
                return _FarmList;
            }
        }

        public bool HasFlowerWomen
        {
            get
            {
                return _FlowerWomen;
            }
        }

        public bool HasCaiLaoBo
        {
            get
            {
                return _CaiLaoBo;
            }
        }


        /// <summary>
        /// initialize a garden
        /// </summary>
        /// <param name="uid">your uid</param>
        /// <param name="fuid">friend uid (owner)</param>
        /// <param name="verify">verify code</param>
        /*
        public Garden(string uid, string fuid, string verify, 
            Network network, MySeedList myseedlist, AntiTheive anti)
        {
            _uid = uid;
            _verify = verify;
            _fuid = fuid;

            _network = network;
            _MySeeds = myseedlist;
            _Anti = anti;
        }
         * */


        public Garden(string uid, Friend friend, string verify,
            Network network, MySeedList myseedlist, AntiTheive anti)
        {
            _uid = uid;
            _verify = verify;
            _fuid = friend.Uid;
            _friend = friend;

            _network = network;
            _MySeeds = myseedlist;
            _Anti = anti;
        }

        public void UpdateInfo()
        {
            string url = "";
            
            // added an interface for my garden, not sure if this is useful
            if (_uid.Equals(_friend.Uid))
            {
                url = Consts.RootURL + Consts.GardenInterface;
                Random r = new Random((int)DateTime.Now.Ticks);

                string data = r.NextDouble().ToString() + "=&_=&class=garden&id=0";
                _network.PostData(url, Encoding.UTF8.GetBytes(data));
            }

            url = Consts.RootURL + Consts.GardenConfUrl + 
                "?verify=" + _verify + "&fuid=" + _fuid;

            try
            {
                string respXML = _network.CallUrl(url);
                XMLParser xmlParser = new XMLParser(respXML);

                _FlowerWomen = !"".Equals(xmlParser.GetNodeValue("/conf/account/flowerwomanurl"));
                _CaiLaoBo = !"".Equals(xmlParser.GetNodeValue("/conf/account/careurl"));
                XmlNodeList nodelist = xmlParser.GetNodeList("/conf/garden");

                _FarmList.Clear();
                for (int i = 0; i < nodelist.Count; i++)
                {
                    if (nodelist.Item(i).NodeType == XmlNodeType.Text)
                        continue;
                    _FarmList.Add(XmlNodeToFarm(nodelist.Item(i)));
                }
            }
            catch (Exception)
            {
                // TODO Auto-generated catch block
            }
        }

        private Farm XmlNodeToFarm(XmlNode node)
        {
            //Farm farm = new Farm(_network, _uid, _fuid, _verify);
            Farm farm = new Farm(_network, _uid, _friend, _verify);

            try
            {
                XmlElement element = (XmlElement)node;

                XmlNode e = element.GetElementsByTagName("farmnum").Item(0);

                farm.FarmNum = Convert.ToInt32(element.GetElementsByTagName("farmnum").Item(0).InnerText);
                farm.Status = Convert.ToInt32(element.GetElementsByTagName("status").Item(0).InnerText);

                if (farm.Status == 0) // farm cannot seed yet
                    return farm;

                farm.Grass = Convert.ToInt32(element.GetElementsByTagName("grass").Item(0).InnerText);
                farm.Water = Convert.ToInt32(element.GetElementsByTagName("water").Item(0).InnerText);
                farm.Vermin = Convert.ToInt32(element.GetElementsByTagName("vermin").Item(0).InnerText);

                farm.Shared = Convert.ToInt32(element.GetElementsByTagName("shared").Item(0).InnerText);

                string cropss = element.GetElementsByTagName("cropsstatus").Item(0).InnerText;

                if (cropss == null || cropss.Equals(""))
                    return farm;

                farm.CropsStatus = Convert.ToInt32(cropss);

                if (farm.Shared > 0)
                    farm.SFUid = element.GetElementsByTagName("fuid").Item(0).InnerText;
                else
                    farm.SFUid = "0";

                farm.Grow = Convert.ToInt32(element.GetElementsByTagName("grow").Item(0).InnerText);
                farm.TotalGrow = Convert.ToInt32(element.GetElementsByTagName("totalgrow").Item(0).InnerText);
                farm.FruitNum = Convert.ToInt32(element.GetElementsByTagName("fruitnum").Item(0).InnerText);
                farm.Name = element.GetElementsByTagName("name").Item(0).InnerText;
                farm.SeedId = element.GetElementsByTagName("seedid").Item(0).InnerText;
                //farm.Crops = element.GetElementsByTagName("crops").Item(0).InnerText;
                farm.Crops = element.GetElementsByTagName("crops").Item(0).InnerText;

                string pat = "已偷过";
                if (farm.Crops.IndexOf(pat) >= 0)
                    farm.Thieved = true;

                pat = "距离收获：\\s*((\\d+)天)?((\\d+)小时)?((\\d+)分)?((\\d+)秒)?";
                Match m = Regex.Match(farm.Crops, pat);
                if (m.Success)
                {
                    int day = (m.Groups[2].Value == null || m.Groups[2].Value == "") ? 0 : Convert.ToInt32(m.Groups[2].Value);
                    int hour = (m.Groups[4].Value == null || m.Groups[4].Value == "") ? 0 : Convert.ToInt32(m.Groups[4].Value);
                    int min = (m.Groups[6].Value == null || m.Groups[6].Value == "") ? 0 : Convert.ToInt32(m.Groups[6].Value);
                    int sec = (m.Groups[8].Value == null || m.Groups[8].Value == "") ? 0 : Convert.ToInt32(m.Groups[8].Value);
                    farm.GrowRemainTime.SetValue(day, hour, min, sec);
                 }

                pat = "再过\\s*((\\d+)天)?((\\d+)小时)?((\\d+)分)?((\\d+)秒)?可偷";
                m = Regex.Match(farm.Crops, pat);
                if (m.Success)
                {
                    int day = (m.Groups[2].Value == null || m.Groups[2].Value == "") ? 0 : Convert.ToInt32(m.Groups[2].Value);
                    int hour = (m.Groups[4].Value == null || m.Groups[4].Value == "") ? 0 : Convert.ToInt32(m.Groups[4].Value);
                    int min = (m.Groups[6].Value == null || m.Groups[6].Value == "") ? 0 : Convert.ToInt32(m.Groups[6].Value);
                    int sec = (m.Groups[8].Value == null || m.Groups[8].Value == "") ? 0 : Convert.ToInt32(m.Groups[8].Value);
                    long ThieveWaitTime = (((day * 24 + hour) * 60 + min) * 60 + sec) * 1000;
                    farm.ThieveWaitTime.SetValue(day, hour, min, sec);
                }

                pat = "剩余：(\\d+?)<br>";
                m = Regex.Match(farm.Crops, pat);
                if (m.Success)
                {
                    farm.RemainNum = (m.Groups[1].Value == null || m.Groups[1].Value == "") ? 0 : Convert.ToInt32(m.Groups[1].Value);
                }

                return farm;
            }
            catch (Exception)
            {
                return farm;
            }
        }

        public void DoAction(ActionType atype)
        {
            Thread ActionThread = null;
            switch (atype)
            { 
                case ActionType.Harvest:
                    ActionThread = new Thread(new ThreadStart(this.Harvest));
                    break;
                case ActionType.AntiGrass:
                    ActionThread = new Thread(new ThreadStart(this.AntiGrass));
                    break;
                case ActionType.Water:
                    ActionThread = new Thread(new ThreadStart(this.Water));
                    break;
                case ActionType.AntiVermin:
                    ActionThread = new Thread(new ThreadStart(this.AntiVermin));
                    break;
                case ActionType.Plough:
                    ActionThread = new Thread(new ThreadStart(this.Plough));
                    break;
                case ActionType.FarmSeedRandom:
                    ActionThread = new Thread(new ThreadStart(this.FarmSeedRandom));
                    break;
            }
            if (ActionThread != null)
            {
                ActionThread.IsBackground = true;
                ActionThread.Start();
            }
        }

        public void UpdateMySeedList()
        {
            _MySeeds.UpdateSeedList(_verify);
        }

        private void Harvest()
        {
            int count = 0;
            TextOutput.PrintLine("Harvest " + _friend.Name + "...");
            if (_Anti.Triggered)
            {
                TextOutput.PrintLine("--- AntiTheive Triggered. ---");
                return;
            }
            if (!_CaiLaoBo && !_FlowerWomen)
            {
                for (int i = 0; i < _FarmList.Count; i++)
                    if (_FarmList[i].CanHarvest() && !_Anti.Triggered)
                    {
                        int result = _FarmList[i].Harvest(_fuid, _verify);
                        if (result == 1)
                            count++;
                        else if (result == -1) // anti
                        {
                            _Anti.Trigger();
                            break;
                        }
                     }
            }
            else
                TextOutput.PrintLine("--- CaiLaoBo or HuaPoPo !!! ---");
            TextOutput.PrintLine("End Harvest " + _friend.Name + ": Total " + count);
        }

        private void AntiGrass()
        {
            int count = 0;
            TextOutput.PrintLine("AntiGrass " + _friend.Name + "...");
            for (int i = 0; i < _FarmList.Count; i++)
                if (_FarmList[i].CanAntiGrass())
                   if (_FarmList[i].AntiGrass())
                       count++;
            TextOutput.PrintLine("End AntiGrass " + _friend.Name + ": Total " + count);
        }

        private void Water()
        {
            int count = 0;
            TextOutput.PrintLine("Water " + _friend.Name + "...");
            for (int i = 0; i < _FarmList.Count; i++)
                if (_FarmList[i].CanWater())
                    if (_FarmList[i].DoWater())
                        count++;
            TextOutput.PrintLine("End Water " + _friend.Name + ": Total " + count);
        }

        private void AntiVermin()
        {
            int count = 0;
            TextOutput.PrintLine("AntiVermin " + _friend.Name + "...");
            for (int i = 0; i < _FarmList.Count; i++)
                if (_FarmList[i].CanVermin())
                    if (_FarmList[i].AntiVermin())
                        count++;
            TextOutput.PrintLine("End AntiVermin " + _friend.Name + ": Total " + count);
        }

        private void Plough() // only self and friends' shared, check status first
        {
            int count = 0;
            string fuid = (_uid.Equals(_fuid)?"0":_fuid);

            TextOutput.PrintLine("Plough " + _friend.Name + "...");
            for (int i = 0; i < _FarmList.Count; i++)
                if (_FarmList[i].CanPlough()) // unkown status
                    if (_FarmList[i].Plough())
                        count++;
            TextOutput.PrintLine("End Plough " + _friend.Name + ": Total " + count);
        }

        private void FarmSeedRandom() // only self and friends' shared
        {
            int count = 0;
            string fuid = (_uid.Equals(_fuid) ? "0" : _fuid);
            //UpdateMySeedList();

            TextOutput.PrintLine("FarmSeed " + _friend.Name + "...");
            for (int i = 0; i < _FarmList.Count; i++)
                if (_FarmList[i].CanFarmSeed())
                {
                    UpdateMySeedList();
                    string seed = _MySeeds.GetRandomSeed();
                    if (!seed.Equals(""))
                    {
                        if (_FarmList[i].FarmSeed(_MySeeds.GetRandomSeed()))
                            count++;
                    }
                    else // no seeds
                        break;
                }
            TextOutput.PrintLine("End Farm " + _friend.Name + ": Total " + count);
        }
    }
}

